﻿using System;
using System.ComponentModel;
using System.Data;
using System.Configuration;
using System.Reflection;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Common.Logging;
using System.IO;
using System.Collections.Generic;
using EQT.Model;
using EQT.Bll;
using EQT.Dal;
using System.Web.Hosting;

public static class Utility
{
    /// <summary>
    /// 顶级菜单项组列表
    /// </summary>
    internal static string[] FUNCTION_GROUP_ID_LIST = new string[] {"HOME","SYS","RPT","EQU","DTT","TSK","DOC" };
    


    private static readonly ILog globalLog= LogManager.GetLogger("Global Logger");
    //private static UriBuilder localfileUribuilder = new UriBuilder(Uri.UriSchemeFile, "/");


    /// <summary>
    /// 全局日志
    /// </summary>
    public static ILog GlobalLog
    {
        get { return Utility.globalLog; }
    }

    static Utility()
    {
        _DaRF = new DaRoleFunction(DaCommon.DefaultDb);
        _RoleManifest = new Dictionary<string, Manifest>();
        //TODO:在这里把每个角色的Mainifest构建出来
        InitRoleManifest();
        dasysCoding = new DaSysCoding();
    }


    public static void BindDataSet2Combox(DataSet ds, DropDownList combox, string TextField, string ValueField)
    {
        combox.Items.Clear();
        combox.DataValueField = ValueField;
        combox.DataTextField = TextField;
        combox.DataSource = ds;
        combox.DataBind();
    }

    #region URI相关工具函数
    /// <summary>
    /// 给定全文件名，返回本地的URI模式；
    /// </summary>
    /// <param name="fullFileName"></param>
    /// <returns></returns>
    public static string GetUri4LocalFile(string fullFileName)
    {
        UriBuilder localfileUribuilder = new UriBuilder(Uri.UriSchemeFile, "/");
        localfileUribuilder.Path = fullFileName;
        return localfileUribuilder.Uri.ToString();
    }

    /// <summary>
    /// 给定目标目录，来源文件名，返回使用了来源文件名作为文件名的全路径名对应的URI。
    /// </summary>
    /// <param name="targetDir"></param>
    /// <param name="fromFileName"></param>
    /// <returns></returns>
    public static string GetDefaultUri4UploadedFile(string targetDir, string fromFileName)
    {
        UriBuilder localfileUribuilder = new UriBuilder(Uri.UriSchemeFile, "/");
        localfileUribuilder.Path = System.IO.Path.Combine(targetDir, fromFileName);
        return localfileUribuilder.Uri.ToString();
    }
    /// <summary>
    /// 给定目标目录，来源文件名，目标文件名（无扩展名），返回完整的目标URI.
    /// </summary>
    /// <param name="targetDir"></param>
    /// <param name="fromFileName"></param>
    /// <param name="toFileNameNoExt"></param>
    /// <returns></returns>
    public static string GetDefaultUri4UploadedFile(string targetDir, string fromFileName, string toFileNameNoExt)
    {

        string toFileName = toFileNameNoExt + System.IO.Path.GetExtension(fromFileName);
        return GetDefaultUri4UploadedFile(targetDir, fromFileName);
    }

    public static string GetLocalFileFromUri(string uri)
    {
        string rc = String.Empty;
        try
        {
            Uri u = new Uri(uri);
            rc = u.LocalPath;
        }
        catch (Exception ex)
        {
            globalLog.Error("URI格式不正确", ex);
            rc = String.Empty;
        }
        return rc;
    }
    #endregion

    #region 权限\菜单相关
    //TODO:应该将菜单权限相关的，放到Site_Config类中；
    internal static Dictionary<string, Manifest> _RoleManifest;

    /// <summary>
    /// 将manifest.xml文件 反序列化成Manifest对象。
    /// 在更改角色的权限定义后，需调用它。
    /// 这里从数据库获取了所有 2009-5-31
    /// </summary>
    /// <param name="amConfigFile">文件路径</param>
    /// <returns></returns>
    public static void InitRoleManifest()
    {
        #region 从XML获取 已经废弃
        //Manifest ret = null;

        //System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(Manifest));
        //StreamReader reader = new StreamReader(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Manifest.xml"));
        //try
        //{
        //    object o = ser.Deserialize(reader);
        //    ret = o as Manifest;
        //}
        //catch (Exception ex)
        //{
        //    throw ex;
        //}
        //finally
        //{
        //    reader.Close();
        //}
        //return ret;       
        #endregion

        _RoleManifest.Clear();
        //从数据库获取每个角色的Manifest
        DaTrole darole = new DaTrole(DaCommon.DefaultDb);
        DaTfunction dafunc = new DaTfunction(DaCommon.DefaultDb);
        List<MoTrole> roles = darole.GetEntities(null);
        if (roles != null && roles.Count > 0)
        {
            foreach(MoTrole r in roles)//对每个角色进行配置
            {
                Manifest mf = new Manifest();
                for (int i = 0; i < FUNCTION_GROUP_ID_LIST.Length; i++)
                {
                    //获取组Func
                    MoTfunction func = dafunc.GetRoleFunctionsViaFuncId(r.Role_Id, FUNCTION_GROUP_ID_LIST[i]);
                    if (func == null || func.Func_Class!="0")//0标识组功能（顶级功能）1标识菜单项，2标识内部子功能
                    {
                        continue;
                    }

                    Group g = new Group();
                    g.DisplayText = func.Func_Name;
                    g.ID = func.Func_Id;
                    g.Url = func.Func_Sign;

                    //菜单项
                    List<MoTfunction> lfunc = dafunc.GetRoleFunctionsViaParentFunc(r.Role_Id, FUNCTION_GROUP_ID_LIST[i]);
                    foreach (MoTfunction m in lfunc)
                    {
                        SubMenu sm = new SubMenu();
                        sm.DisPlayText = m.Func_Name;
                        sm.Url = SiteConfig.Site_Base + "/" + m.Func_Sign;
                        g.SubMenuList.Add(sm);
                    }
                    if (g.SubMenuList.Count > 0 && String.IsNullOrEmpty(g.Url)) g.Url = g.SubMenuList[0].Url;

                    if (g.SubMenuList.Count > 0)
                    {
                        //将一个Group添加到
                        mf.GroupList.Add(g);
                        globalLog.DebugFormat("组织完成菜单组{0}", g.ID);
                    }
                    else
                    {
                        globalLog.WarnFormat("菜单组{0}没有一个URL", g.ID);
                    }

                }//所有组都遍历完成
                _RoleManifest.Add(r.Role_Id, mf);

            }
        }
        else
        {
            string error = "系统没有配置有效角色！";
            globalLog.Error(error);
            MessageDisplay.DisplayMessage("初始化错误",error);
        }



    }


    internal static DaRoleFunction _DaRF;
    /// <summary>
    /// 检查某个页面上的权限 
    /// </summary>
    /// <param name="roleId"></param>
    /// <param name="funcId">FuncIdConstants中的常量定义</param>
    /// <param name="p"></param>
    /// <returns></returns>
    public static bool CheckRights(string funcId, Page p)
    {
        UserContext uc = p.Session["USER_CONTEXT"] as UserContext;

        if (uc == null)
        {
            globalLog.ErrorFormat("用户上下文为空.{0},{1}", funcId, p);
            return false;
        }
        return _DaRF.IsExist(uc.RoleID, funcId);
        
    }


    #endregion



    /// <summary>
    /// 从数据库查询该用户可以操作的菜单项.
    /// 页面资源的Func_Class是URL,Func_ID是相对URL，Func_Name是URL显示名称.
    /// </summary>
    /// <param name="uc">用户上下文</param>
    /// <returns></returns>
    public static Manifest GetUserManifestModel(UserContext uc)
    {
        return _RoleManifest[uc.RoleID];
    }

    public static void SiteError(string msg)
    {
        wwMessageDisplay.DisplayMessage("系统错误", msg, "~/login.aspx", 10);
    }

    public static void SiteError(string msg, HttpResponse response)
    {
        wwMessageDisplay.DisplayMessage("系统错误", msg, "~/login.aspx", 10);

    }

    #region 报告状态
    /// <summary>
    /// 绑定报告状态列表，包含【全部】项
    /// </summary>
    /// <param name="listCtl"></param>
    public static void BindReportStatusWithAll(System.Web.UI.WebControls.ListControl listCtl,List<EQT.Model.MoSysCoding> list)
    {
        listCtl.DataSource = list;
        listCtl.DataTextField = "Content";
        listCtl.DataValueField = "Class1"; //数据库中存储的，是字符串，真正使用时，应转成整数判断。
        listCtl.DataBind();
        listCtl.SelectedValue = "ALL";
    }
    /// <summary>
    /// 绑定有效的报告状态列表
    /// </summary>
    /// <param name="listCtl"></param>
    public static void BindReportStatus(System.Web.UI.WebControls.ListControl listCtl, List<EQT.Model.MoSysCoding> list)
    {
        listCtl.DataSource = list;
        listCtl.DataTextField = "Content";
        listCtl.DataValueField = "Class1"; //存数据库时，应该将它转换成整数
        listCtl.DataBind();
    }

    #endregion

    #region 通知相关
    public static void SaveNoticeContent(string fileshortname, string content)
    {
        if (!fileshortname.ToLower().EndsWith(".htm"))
        {
            fileshortname += ".htm";
        }
        string filepath = Path.Combine(HttpContext.Current.Request.MapPath("."), "NoticeFile\\" + fileshortname);

        File.WriteAllText(filepath, content);
    }

    public static void DeleteNoticeContent(string fileshortname)
    {
        if (!fileshortname.ToLower().EndsWith(".htm"))
        {
            fileshortname += ".htm";
        }
        string filepath = Path.Combine(HttpContext.Current.Request.MapPath("."), "NoticeFile\\" + fileshortname);
        File.Delete(filepath);
    }

    public static string ReadNoticeContent(string fileshortname)
    {
        if (!fileshortname.ToLower().EndsWith(".htm"))
        {
            fileshortname += ".htm";
        }
        try
        {
            string filepath = Path.Combine(HttpContext.Current.Request.MapPath("."), "NoticeFile\\" + fileshortname);
            if (!File.Exists(filepath))
            {
                return "";
            }
            return File.ReadAllText(filepath);
        }
        catch (Exception ex)
        {
            globalLog.Error("读取通知失败.", ex);

            return "";
        }
    }
    #endregion

    #region 系统编码绑定 辅助函数

    private static DaSysCoding dasysCoding;

    public static void BindListCtl2Dic(System.Web.UI.WebControls.ListControl listCtl, System.Collections.IDictionary dic)
    {
        listCtl.DataSource = dic;
        listCtl.DataTextField = "Value";
        listCtl.DataValueField = "Key";
        listCtl.DataBind();
    }


    /// <summary>
    /// 将系统编码绑定到一个列表控件，如DataListControl
    /// </summary>
    /// <param name="listCtl"></param>
    /// <param name="grpCode"></param>
    public static void BindSysCode(System.Web.UI.WebControls.ListControl listCtl, string grpCode)
    {
        List<EQT.Model.MoSysCoding> list = dasysCoding.GetEntities(String.Format(" WHERE GRPCODE='{0}' ORDER BY Code", grpCode));

        BindSysCode(listCtl, list);
    }
    /// <summary>
    /// 将系统编码绑定到一个列表控件，如DataListControl，包含自定义的【全部】编码项，【全部】的Code="ALL"
    /// </summary>
    /// <param name="listCtl"></param>
    /// <param name="grpCode"></param>
    public static void BindSysCodeWithAll(System.Web.UI.WebControls.ListControl listCtl, string grpCode)
    {

        //List<MoSysCoding> list = dasysCoding.GetEntities(String.Format(" WHERE GRPCODE='{0}' ORDER BY Code", grpCode));
        //list.Insert(0, _all_mo_sysCoding);
        //BindSysCode(listCtl, list);
    }
    /// <summary>
    /// 将系统编码绑定到一个列表控件，如DataListControl，包含自定义的【无】编码项，【无】的Code="NONE"
    /// </summary>
    /// <param name="listCtl"></param>
    /// <param name="grpCode"></param>
    public static void BindSysCodeWithNone(System.Web.UI.WebControls.ListControl listCtl, string grpCode)
    {
        //List<MoSysCoding> list = dasysCoding.GetEntities(String.Format(" WHERE GRPCODE='{0}' ORDER BY Code", grpCode));
        //list.Insert(0, _none_mo_sysCoding);
        //BindSysCode(listCtl, list);
    }

    private static void BindSysCode(System.Web.UI.WebControls.ListControl listCtl, List<EQT.Model.MoSysCoding> list)
    {
        if (list != null && list.Count > 0)
        {
            listCtl.DataSource = list;
            listCtl.DataTextField = "Content";
            listCtl.DataValueField = "Code";
            listCtl.ToolTip = "Description";
            listCtl.DataBind();

        }
    }
    #endregion

    #region 枚举工具函数
    /// <summary>
    /// Returns the value of the DescriptionAttribute if the specified Enum value has one.
    /// If not, returns the ToString() representation of the Enum value.
    /// </summary>
    /// <param name="value">The Enum to get the description for</param>
    /// <returns></returns>
    public static string GetDescription(System.Enum e)
    {
        FieldInfo EnumInfo = e.GetType().GetField(e.ToString());
        DescriptionAttribute[] EnumAttributes = (DescriptionAttribute[])EnumInfo.
            GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (EnumAttributes.Length > 0)
        {
            return EnumAttributes[0].Description;
        }
        return e.ToString();

       
       
            
    }

    /// <summary>
    /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivilant enumerated object.
    /// Note: Utilised the DescriptionAttribute for values that use it.
    /// </summary>
    /// <param name="enumType">The System.Type of the enumeration.</param>
    /// <param name="value">A string containing the name or value to convert.</param>
    /// <returns></returns>
    public static object Parse(Type enumType, string value)
    {
        return Parse(enumType, value, false);
    }

    /// <summary>
    /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivilant enumerated object.
    /// A parameter specified whether the operation is case-sensitive.
    /// Note: Utilised the DescriptionAttribute for values that use it.
    /// </summary>
    /// <param name="enumType">The System.Type of the enumeration.</param>
    /// <param name="value">A string containing the name or value to convert.</param>
    /// <param name="ignoreCase">Whether the operation is case-sensitive or not.</param>
    /// <returns></returns>
    public static object Parse(Type enumType, string value, bool ignoreCase)
    {
        if (ignoreCase)
            value = value.ToLower();

        foreach (System.Enum val in System.Enum.GetValues(enumType))
        {
            string comparisson = GetDescription(val);
            if (ignoreCase)
                comparisson = comparisson.ToLower();
            if (GetDescription(val) == value)
                return val;
        }

        return System.Enum.Parse(enumType, value, ignoreCase);
    }
    #endregion 枚举工具函数

    #region 流复制

    internal const int STREAM_COPY_BUFFER_SIZE = 32768;


    /// <summary>
    /// 流复制函数
    /// </summary>
    /// <param name="input"></param>
    /// <param name="output"></param>
    public static void CopyStream(Stream input, Stream output)
    {
        //int bufferSize = 32768;
        byte[] buffer = new byte[STREAM_COPY_BUFFER_SIZE];
        while (true)
        {
            int read = input.Read(buffer, 0, buffer.Length);
            if (read <= 0)
            {
                return;
            }
            output.Write(buffer, 0, read);
        }
    }
    #endregion

    #region 路径转换
    /// <summary>
    /// 将Web站点下的绝对路径转换为相对于指定页面的虚拟路径
    /// </summary>
    /// <param name="page">当前页面指针，一般为this</param>
    /// <param name="specifiedPath">绝对路径</param>
    /// <returns>虚拟路径, 型如: ../../</returns>
    public static string ConvertSpecifiedPathToRelativePathForPage(Page page, string specifiedPath)
    {
        // 根目录虚拟路径
        string virtualPath = page.Request.ApplicationPath;
        // 根目录绝对路径
        string pathRooted = HostingEnvironment.MapPath(virtualPath);
        // 页面虚拟路径
        string pageVirtualPath = page.Request.Path;
        if (!Path.IsPathRooted(specifiedPath) || specifiedPath.IndexOf(pathRooted) == -1)
        {
            throw new Exception(string.Format("\"{0}\"是虚拟路径而不是绝对路径!", specifiedPath));
        }
        // 转换成相对路径 
        //(测试发现，pathRooted 在 VS2005 自带的服务器跟在IIS下根目录或者虚拟目录运行似乎不一样,
        // 有此地方后面会加"\", 有些则不会, 为保险起见判断一下)
        if (pathRooted.Substring(pathRooted.Length - 1, 1) == "\\")
        {
            specifiedPath = specifiedPath.Replace(pathRooted, "/");
        }
        else
        {
            specifiedPath = specifiedPath.Replace(pathRooted, "");
        }
        string relativePath = specifiedPath.Replace("\\", "/");
        string[] pageNodes = pageVirtualPath.Split('/');
        // 减去最后一个页面和前面一个 "" 值
        int pageNodesCount = pageNodes.Length - 2;
        for (int i = 0; i < pageNodesCount; i++)
        {
            relativePath = "/.." + relativePath;
        }
        if (pageNodesCount > 0)
        {
            // 如果存在 ".." , 则把最前面的 "/" 去掉
            relativePath = relativePath.Substring(1, relativePath.Length - 1);
        }
        return relativePath;
    }

    /// <summary>
    /// 将Web站点下的绝对路径转换为虚拟路径
    /// 注：非Web站点下的则不转换
    /// </summary>
    /// <param name="page">当前页面指针，一般为this</param>
    /// <param name="specifiedPath">绝对路径</param>
    /// <returns>虚拟路径, 型如: ~/</returns>
    public static string ConvertSpecifiedPathToRelativePath(Page page, string specifiedPath)
    {
        string virtualPath = page.Request.ApplicationPath;
        string pathRooted = HostingEnvironment.MapPath(virtualPath);
        if (!Path.IsPathRooted(specifiedPath) || specifiedPath.IndexOf(pathRooted) == -1)
        {
            return specifiedPath;
        }
        if (pathRooted.Substring(pathRooted.Length - 1, 1) == "\\")
        {
            specifiedPath = specifiedPath.Replace(pathRooted, "~/");
        }
        else
        {
            specifiedPath = specifiedPath.Replace(pathRooted, "~");
        }
        string relativePath = specifiedPath.Replace("\\", "/");
        return relativePath;
    }

    /// <summary>
    /// 从绝对路径读图形文件。
    /// </summary>
    /// <param name="page"></param>
    /// <param name="filePath"></param>
    public static void ReadImageFile(Page page, string filePath)
    {
        string contenttype = string.Empty;
        string ext = (new FileInfo(filePath)).Extension;
        switch (ext.ToLower())
        {
            case ".png":
                contenttype = "image/png";
                break;
            case ".tiff":
                contenttype = "image/tiff";
                break;
            case ".jpeg":
                contenttype = "image/JPEG";
                break;
            case ".jpg":
                contenttype = "image/JPEG";
                break;
            case ".gif":
                contenttype = "image/GIF";
                break;
            case ".bmp":
                contenttype = "application/x-bmp";
                break;
            default:
                break;
        }

        if (ext != string.Empty && File.Exists(filePath))
        {
            page.Response.ContentType = contenttype;


            page.Response.BinaryWrite(File.ReadAllBytes(filePath));
        }
    }

    #endregion

    #region 查询过滤字符串辅助函数

    /// <summary>
    /// 
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="parameter"></param>
    /// <param name="filterType">1=等于，2=LIKE</param>
    /// <returns></returns>
    public static string GenerateQueryFilterString(string columnName,string parameter,int filterType)
    {
        if (String.IsNullOrEmpty(parameter)) return null;
        string p = parameter.Trim();
        if (p.Length == 0) return null;

        return filterType == 1 ? String.Format(" {0}='{1}' ", columnName, parameter) : 
            String.Format(" {0} LIKE '%{1}%' ", columnName, p);

    }

    /// <summary>
    /// 时间比较
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="parameter"></param>
    /// <param name="opter">可以是任何时间操作符,如 大于，等于，小于，小于等于....   </param>
    /// <returns></returns>
    public static string GenerateQueryFilter1DateTime(string columnName, string opter, string parameter)
    {
        if (String.IsNullOrEmpty(parameter)) return null;
        string p = parameter.Trim();
        if (p.Length == 0) return null;

        return String.Format(" {0} {3} convert(datetime, '{1}',{2}) ", columnName, p, SiteConfig.DateTimeRegion,opter);
    }


    /// <summary>
    /// 时间比较
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="parameter"></param>
    /// <param name="opter">可以是任何时间操作符,如 大于，等于，小于，小于等于....   </param>
    /// <returns></returns>
    public static string GenerateQueryFilter2DateTime(string columnName,string parameter1,string parameter2)
    {
        if (String.IsNullOrEmpty(parameter1)||String.IsNullOrEmpty(parameter2)) return null;
        string p1 = parameter1.Trim();
        if (p1.Length == 0) return null;
        string p2 = parameter2.Trim();
        if (p2.Length == 0) return null;

        return String.Format(" {0} between convert(datetime, '{1}',{2})  AND convert(datetime, '{3}',{2}) ", columnName, p1, SiteConfig.DateTimeRegion, p2);
    }

    /// <summary>
    /// 数值比较1参数
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="opter">任何可以作用于数字的操作符，如大小于，等于</param>
    /// <param name="parameter"></param>
    /// <returns></returns>
    public static string GenerateQueryFilter1Number(string columnName, string opter, string parameter)
    {
        if (String.IsNullOrEmpty(parameter)) return null;
        string p = parameter.Trim();
        if (p.Length == 0) return null;

        return String.Format(" {0} {1} {2} ", columnName, opter,p);
    }

    /// <summary>
    /// 整数掩码操作
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="opter"></param>
    /// <param name="parameter"></param>
    /// <returns></returns>
    public static string GenerateQueryFilterIntMaskAnd(string columnName, string opter, int parameter)
    {
        return String.Format(" {0}&{1} <>0 ", columnName, parameter);
    }

   

    /// <summary>
    /// 数值比较2参数
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="opter"></param>
    /// <param name="parameter"></param>
    /// <returns></returns>
    public static string GenerateQueryFilter2Number(string columnName, string parameter1,string parameter2)
    {
        if (String.IsNullOrEmpty(parameter1) || String.IsNullOrEmpty(parameter2)) return null;
        string p1 = parameter1.Trim();
        if (p1.Length == 0) return null;
        string p2 = parameter2.Trim();
        if (p2.Length == 0) return null;

        return String.Format(" {0} between {1} AND {2} ", columnName, p1, p2);
    }





    #endregion

    /// <summary>
    /// 工具函数，将字符串数组转化成/分隔的字符串
    /// </summary>
    /// <param name="strList"></param>
    /// <returns></returns>
    public static string ConvertStringListToOneRow(string[] strList)
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        for (int i = 0; i < strList.Length; i++)
        {
            sb.Append(strList[i]);
            if (i < strList.Length - 1)
            {
                sb.Append("/");
            }
        }
        return sb.ToString();
    }


}
